package com.codegeek.project.slope.controller;

import com.alibaba.fastjson.JSON;
import com.codegeek.common.utils.SecurityUtils;
import com.codegeek.common.utils.poi.ExcelUtil;
import com.codegeek.framework.aspectj.lang.annotation.Log;
import com.codegeek.framework.aspectj.lang.enums.BusinessType;
import com.codegeek.framework.web.controller.BaseController;
import com.codegeek.framework.web.domain.AjaxResult;
import com.codegeek.framework.web.page.TableDataInfo;
import com.codegeek.project.ExcelHelper.CGSlopeSensorExcel;
import com.codegeek.project.communicate.RedisDBService;
import com.codegeek.project.mybatisTypeHandler.struct.CGSensorTypeItem;
import com.codegeek.project.mybatisTypeHandler.struct.CGSensorTypeParam;
import com.codegeek.project.slope.domain.SlopeDevice;
import com.codegeek.project.slope.domain.SlopeMonitorItem;
import com.codegeek.project.slope.domain.SlopeSensor;
import com.codegeek.project.slope.domain.SlopeSensorType;
import com.codegeek.project.slope.service.ISlopeDeviceService;
import com.codegeek.project.slope.service.ISlopeMonitorItemService;
import com.codegeek.project.slope.service.ISlopeSensorService;
import com.codegeek.project.slope.service.ISlopeSensorTypeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 传感器Controller
 *
 * @author codegeek
 * @date 2020-02-20
 */
@RestController
@RequestMapping("/slope/sensor")
@Api(value = "传感器Controller", tags = {"传感器操作接口"})
public class SlopeSensorController extends BaseController {
    @Autowired
    private ISlopeSensorService slopeSensorService;

    @Autowired
    private ISlopeDeviceService slopeDeviceService;

    @Autowired
    private ISlopeMonitorItemService slopeMonitorItemService;

    @Autowired
    private ISlopeSensorTypeService slopeSensorTypeService;

    @Autowired
    private RedisDBService redisDBService;

    /**
     * 查询传感器列表
     */
    @ApiOperation("查询传感器列表")
    @GetMapping("/list")
    @PreAuthorize("@ss.hasPermi('slope:sensor:list')")
    public TableDataInfo list(SlopeSensor slopeSensor) {
        startPage();
        List<SlopeSensor> list = slopeSensorService.selectSlopeSensorList(slopeSensor);
        return getDataTable(list);
    }

    /**
     * 删除传感器
     */
    @ApiOperation("删除传感器")
    @Log(title = "设备管理", businessType = BusinessType.DELETE)
    @PostMapping("/remove/{sensorIds}")
    @PreAuthorize("@ss.hasPermi('slope:sensor:remove')")
    public AjaxResult remove(@PathVariable Long[] sensorIds) {
        return toAjax(slopeSensorService.deleteSlopeSensorByIds(sensorIds));
    }

    /**
     * 查询传感器列表
     */
    @ApiOperation("查询传感器列表")
    @GetMapping("/indexSensorList")
    @PreAuthorize("@ss.hasPermi('slope:sensor:indexSensor')")
    public TableDataInfo indexSensorList(SlopeSensor slopeSensor) {
        startPage();
        slopeSensor.setIsValid(0);//只查询启用状态的
        List<SlopeSensor> list = slopeSensorService.selectSlopeSensorList(slopeSensor);
        return getDataTable(list);
    }

    /**
     * 查询传感器列表
     */
    @ApiOperation("传感器管理")
    @GetMapping("/listManage")
    @PreAuthorize("@ss.hasPermi('slope:manage:list')")
    public TableDataInfo listManage(SlopeSensor slopeSensor) {
        startPage();
        List<SlopeSensor> list = slopeSensorService.selectSlopeSensorList2(slopeSensor);
        return getDataTable(list);
    }

    /**
     * 检查imei是否重复
     *
     * @param imei
     * @return
     */
    @ApiOperation("检查imei是否重复")
    @GetMapping("/checkIMEI")
    public AjaxResult checkIMEI(String imei) {
        return AjaxResult.success(slopeSensorService.checkIMEI(imei));

    }

    /**
     * 导出传感器列表
     */
    @ApiOperation("导出传感器列表")
    @Log(title = "设备管理", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    @PreAuthorize("@ss.hasPermi('slope:sensor:export')")
    public AjaxResult export(SlopeSensor slopeSensor) {
        List<SlopeSensor> list = slopeSensorService.selectSlopeSensorList(slopeSensor);
        List<CGSlopeSensorExcel> sensorExcelList = new ArrayList<>();
        for (SlopeSensor sensor : list) {
            CGSlopeSensorExcel sensorExcel = new CGSlopeSensorExcel();
            SlopeDevice device = sensor.getDevice();
            sensorExcel.setMonitorDetail(sensor.getMonitorDetail());
            sensorExcel.setSensorTypeID(sensor.getSensorType().getTypeName());
            sensorExcel.setSensorName(device.getDeviceName());
            sensorExcel.setSensorDescription(device.getDescription());
            sensorExcel.setSensorNumber(device.getNumber());
            sensorExcel.setImei(device.getImei());
            sensorExcel.setPointId(device.getPointId());
            sensorExcel.setSupplierId(device.getSupplierId());
            sensorExcel.setIsValid(device.getIsValid());
            sensorExcel.setMonitorItems(sensor.getMonitorItems() == null ? null : JSON.toJSONString(sensor.getMonitorItems()));
            sensorExcel.setBaseParams(sensor.getBaseParams() == null ? null : JSON.toJSONString(sensor.getBaseParams()));
            sensorExcelList.add(sensorExcel);
        }


        ExcelUtil<CGSlopeSensorExcel> util = new ExcelUtil<CGSlopeSensorExcel>(CGSlopeSensorExcel.class);
        return util.exportExcel(sensorExcelList, "传感器列表");
    }

    /**
     * 获取传感器详细信息
     */
    @ApiOperation("获取传感器详细信息")
    @GetMapping(value = "/{sensorId}")
    @PreAuthorize("@ss.hasPermi('slope:manage:query')")
    public AjaxResult getInfo(@PathVariable("sensorId") Long sensorId) {
        return AjaxResult.success(slopeSensorService.selectSlopeSensorById(sensorId));
    }

    /**
     * 新增传感器
     */
    @ApiOperation("新增传感器")
    @Log(title = "设备管理", businessType = BusinessType.INSERT)
    @PostMapping
    @Transactional
    @PreAuthorize("@ss.hasPermi('slope:sensor:add')")
    public AjaxResult add(@RequestBody SlopeSensor slopeSensor) {
        if (slopeSensor.getDevice() == null) {
            return AjaxResult.error("设备参数错误");
        }
        int iRet = 0;
        SlopeDevice device = slopeSensor.getDevice();
        device.setCreateBy(SecurityUtils.getUsername());
        device.setState(0);         //默认设置为离线
        if (slopeDeviceService.insertSlopeDevice(device) > 0) {
            slopeSensor.setDeviceId(device.getDeviceId());
            iRet = slopeSensorService.insertSlopeSensor(slopeSensor);
            if (iRet > 0) {
                for (SlopeMonitorItem item : slopeSensor.getMonitorItems()) {
                    item.setSensorId(slopeSensor.getSensorId());
                    slopeMonitorItemService.insertSlopeMonitorItem(item);
                }
            }
        }
        return toAjax(iRet);
    }

    /**
     * 修改传感器
     */
    @ApiOperation("修改传感器")
    @Log(title = "设备管理", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @Transactional
    @PreAuthorize("@ss.hasPermi('slope:sensor:edit')")
    public AjaxResult edit(@RequestBody SlopeSensor slopeSensor) {
        slopeDeviceService.updateSlopeDevice(slopeSensor.getDevice());          //更新设备数据
        int iRet = slopeSensorService.updateSlopeSensor(slopeSensor);
        //更新监测项数据
        if (slopeSensor.getMonitorItems() != null) {
            for (SlopeMonitorItem item : slopeSensor.getMonitorItems()) {
                slopeMonitorItemService.updateSlopeMonitorItem(item);
            }
        }
        return toAjax(iRet);
    }

    /**
     * 修改状态
     */
    @ApiOperation("修改状态")
    @Log(title = "设备管理", businessType = BusinessType.UPDATE)
    @PostMapping("/changeIsValid")
    @PreAuthorize("@ss.hasPermi('slope:sensor:disable')")
    public AjaxResult changeIsValid(@RequestBody SlopeSensor slopeSensor) {
        String isValid = slopeSensor.getDevice().getIsValid();
        //禁用
        if (isValid.equals("1")) {
            SlopeSensor sensor = slopeSensorService.selectSlopeSensorById(slopeSensor.getSensorId());
            for (SlopeMonitorItem item : sensor.getMonitorItems()) {
                redisDBService.saveItemHistoryData(sensor.getDevice().getImei(), item);
            }
            redisDBService.clearSensorHistory(sensor.getDevice().getImei());
        }
        return toAjax(slopeSensorService.changeStatus(slopeSensor));
    }


    @ApiOperation("下载Excel")
    @GetMapping("/downloadModel")
    @PreAuthorize("@ss.hasPermi('slope:sensor:import')")
    public AjaxResult downloadModel() {
        ExcelUtil<CGSlopeSensorExcel> util = new ExcelUtil<CGSlopeSensorExcel>(CGSlopeSensorExcel.class);
//        ExcelUtil<SlopeSensor> util = new ExcelUtil<SlopeSensor>(SlopeSensor.class);
        return util.exportExcel(null, "传感器");
    }

    @ApiOperation("导入Excel")
    @Log(title = "设备管理", businessType = BusinessType.IMPORT)
    @PostMapping("/importData")
    @PreAuthorize("@ss.hasPermi('slope:sensor:import')")
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception {
        ExcelUtil<CGSlopeSensorExcel> util = new ExcelUtil<CGSlopeSensorExcel>(CGSlopeSensorExcel.class);
        List<CGSlopeSensorExcel> sensorList = util.importExcel(file.getInputStream());
        List<Map<String, Object>> imeiList = slopeDeviceService.selectAllDeviceImei();
        int iSuccess = 0;
        for (CGSlopeSensorExcel sensorExcel : sensorList) {
            Map<String, Object> map = new HashMap<>();
            map.put("imei", sensorExcel.getImei());
            // 重复的时候不执行
            if (imeiList.contains(map)) {
                continue;
            }
            if (sensorExcel.getSensorName() != null && sensorExcel.getSensorName() != "" && saveSlopeSensor(sensorExcel)) {
                iSuccess++;
            }
        }

        String message = "共导入" + sensorList.size() + "条，成功" + iSuccess + "条";
        return AjaxResult.success(message);
    }


    @Transactional(rollbackFor = Exception.class)
    public boolean saveSlopeSensor(CGSlopeSensorExcel sensorExcel) {
        //todo 事务未起作用
        //todo 存在性验证,
//        SlopeDevice checkExist=new SlopeDevice();
//        checkExist.setDeviceName(sensorExcel.getSensorName());
//        if(slopeDeviceService.selectSlopeDeviceList(checkExist).size()>0){
//            return false;
//        }
        boolean bRet = false;
        SlopeDevice device = new SlopeDevice();
        String isValid = sensorExcel.getIsValid() != null ? (("是".equals(sensorExcel.getIsValid().trim()) || "0".equals(sensorExcel.getIsValid().trim())) ? "0":"1") : "1";
        device.setIsValid(isValid);
        device.setDeviceName(sensorExcel.getSensorName());
        device.setNumber(sensorExcel.getSensorNumber());
        device.setImei(sensorExcel.getImei());
        device.setPointId(sensorExcel.getPointId());
        device.setSupplierId(sensorExcel.getSupplierId());
        device.setCreateBy(SecurityUtils.getUsername());
        //离线
        device.setState(0);
        device.setDescription(sensorExcel.getSensorDescription());

        if (slopeDeviceService.insertSlopeDevice(device) > 0) {
            SlopeSensorType type = slopeSensorTypeService.selectSlopeSensorTypeByName(sensorExcel.getSensorTypeID());
            SlopeSensor sensor = new SlopeSensor();
            sensor.setDeviceId(device.getDeviceId());
            sensor.setMonitorDetail(sensorExcel.getMonitorDetail());
            sensor.setBaseParams(CGSensorTypeParam.parseListFromJsonString(sensorExcel.getBaseParams()));
            sensor.setSensorTypeId(type.getSensorTypeId());

            if (type != null && slopeSensorService.insertSlopeSensor(sensor) > 0) {
                try {
                    //监测项
                    List<SlopeMonitorItem> items = SlopeMonitorItem.parseListFromJsonString(sensorExcel.getMonitorItems());
                    Map<String, SlopeMonitorItem> dataMap = new HashMap();
                    if (items != null) {
                        for (SlopeMonitorItem item : items) {
                            dataMap.put(item.getItemName(), item);
                        }
                    }
                    for (CGSensorTypeItem item : type.getTypeItems()) {
                        SlopeMonitorItem monitorItem = new SlopeMonitorItem();
                        monitorItem.setSensorId(sensor.getSensorId());
                        monitorItem.setItemName(item.getName());
                        monitorItem.setItemUnit(item.getUnit());
                        monitorItem.setThreshold1(dataMap.containsKey(item.getName()) ? dataMap.get(item.getName()).getThreshold1() : 30);
                        monitorItem.setThreshold2(dataMap.containsKey(item.getName()) ? dataMap.get(item.getName()).getThreshold2() : 50);
                        monitorItem.setThreshold3(dataMap.containsKey(item.getName()) ? dataMap.get(item.getName()).getThreshold3() : 70);
                        slopeMonitorItemService.insertSlopeMonitorItem(monitorItem);
                    }

                    //传感器参数
                    List<CGSensorTypeParam> baseParams = CGSensorTypeParam.parseListFromJsonString(sensorExcel.getBaseParams());
                    Map<String, CGSensorTypeParam> paramMap = new HashMap();
                    if (baseParams != null) {
                        for (CGSensorTypeParam item : baseParams) {
                            paramMap.put(item.getName(), item);
                        }
                    }
                    List<CGSensorTypeParam> newParams = type.getTypeParams();
                    if (newParams != null) {
                        for (CGSensorTypeParam param : newParams) {
                            if (paramMap.containsKey(param.getName())) {
                                param.setValue(paramMap.get(param.getName()).getValue());
                            }
                        }
                    }
                    bRet = true;
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
            }
        }
        return bRet;
    }
}
